package lang

import (
	"reflect"
	"strconv"
)

func ToFloat(v interface{}) (float64, error) {
	rt := reflect.TypeOf(v)
	if nil == rt {
		return 0, nil
	}

	rv := reflect.ValueOf(v)
	if reflect.Ptr == rv.Kind() {
		rv = rv.Elem()
	}

	var kind = rv.Kind()
	switch kind {
	case reflect.String:
		return strconv.ParseFloat(rv.String(), 64)
	case reflect.Float32, reflect.Float64:
		return rv.Float(), nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return float64(rv.Int()), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return float64(rv.Uint()), nil
	}

	return 0, nil
}
